package com.woohua.thread.lockscene;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/***
 * @title StampedLock
 * @description: StampedLock 的性能比 ReentrantReadWriteLock 高，而 ReentrantReadWriteLock是每次都要对锁操作加锁，额外的加锁操作增加了开销。
 *              注意：
 *                  虽然在这里StampedLock 性能更高，但是StampedLock也有一些使用约束：
 *                   1、不支持重入
 *                   3、悲观读锁、写锁都不支持条件变量
 * @author woo hua
 * @version 1.0.0
 * @create 2023/3/21 14:09
 **/
public class StampedLockDemo {

    private static int MAX_READ_TIMES = 2000;   // 最大读取次数
    private static int TOTAL_THREAD_NUM = 10;   // 总共线程数
    private static int WRITE_THREAD_NUM = 1;   // 写线程数
    private static int READ_THREAD_NUM = TOTAL_THREAD_NUM - WRITE_THREAD_NUM;   // 读线程数
    private static boolean isStop = false;
    private static long startTime = System.currentTimeMillis();

    public static void main(String[] args) {
        StampedLockCache stampedLockCache = new StampedLockCache();
        ExecutorService executorService = Executors.newFixedThreadPool(TOTAL_THREAD_NUM);
        AtomicInteger value = new AtomicInteger();
        value.getAndIncrement();


        for (int i = 0; i < WRITE_THREAD_NUM; i++) {
            executorService.submit(() -> {
                while (true) {
//                    sleep(20);  // 模拟一段时间内没有写操作

                    int v = value.getAndIncrement();
                    stampedLockCache.put(1001, v);
                    System.out.println(Thread.currentThread().getName() + "-写 value: " + v + " " + new Date());

                    if (isStop) {
                        break;
                    }
                }
            });
        }

        for (int i = 0; i < READ_THREAD_NUM; i++) {
            executorService.submit(() -> {
                int callTimes = 0;
                while (true) {
                    System.out.println(Thread.currentThread().getName() + "-读 value: " + stampedLockCache.get(1001) +
                            " " + new Date());

                    callTimes++;
                    if (callTimes == MAX_READ_TIMES) {
                        isStop = true;
                        System.out.println("cost time: " + (System.currentTimeMillis() - startTime));
                        stampedLockCache.printTime();
                        break;
                    }
                }
            });
        }
    }

    public static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
    }

}
